#include "libgensql.h"
extern "C" {
#include "sqlite3.h"
};
#include <string>
using namespace std;
#ifdef _DEBUG
#pragma comment(lib, "..\\..\\lib\\debug\\libyate.lib")
#pragma comment(lib, "..\\..\\lib\\debug\\sqlite3.lib")
#else
#pragma comment(lib, "..\\..\\lib\\release\\libyate.lib")
#pragma comment(lib, "..\\..\\lib\\release\\sqlite3.lib")
#endif

#define offsetof( TYPE, MEMBER ) ( (size_t) &( (TYPE *) 0)->MEMBER)
#define sizeofof( TYPE, MEMBER ) ( sizeof(( (TYPE *) 0)->MEMBER))

GenSQLModule::GenSQLModule() :
	Module("GenSQL", "misc") {
}

GenSQLModule::~GenSQLModule() {
	Output("Unload module GenSQL");
}

void GenSQLModule::initialize() {
	Output("Initializing module GenSQL");
	Engine::install(new MessageRelay("engine.start", this, Private, 150));
	installRelay(Private + 1, "engine.stop");
}

extern db_field *_field;
extern db_struct* _struct;

#if 0

#if 1
#define STRUCT_ID 2
typedef struct _license {
	char	uuid[64];
	char	create_time[64];
	char	expire_time[64];
	char	description[512];
	int		permission;
	int		type;
} license;

int order_id = 0;
static db_field license_field[] = {
	{STRUCT_ID, order_id ++, offsetof(license, uuid), B_STRING, sizeofof(license, uuid), "uuid"},
	{STRUCT_ID, order_id ++, offsetof(license, create_time), B_STRING, sizeofof(license, create_time), "create_time"},
	{STRUCT_ID, order_id ++, offsetof(license, expire_time), B_STRING, sizeofof(license, expire_time), "expire_time"},
	{STRUCT_ID, order_id ++, offsetof(license, description), B_STRING, sizeofof(license, description), "description"},
	{STRUCT_ID, order_id ++, offsetof(license, permission), B_INT, sizeofof(license, permission), "permission"},
	{STRUCT_ID, order_id ++, offsetof(license, type), B_INT, sizeofof(license, type), "type"},
	{-1,}
};
db_field *_field = license_field;

static db_struct license_struct = {STRUCT_ID, sizeof(license)};
db_struct* _struct = &license_struct;
#endif

#if 0
#define STRUCT_ID 3
typedef struct _android {
	char	uuid[64];
	char	build_brand[64];
	char	build_model[64];
	int		build_sdk_int;
	char	build_board[64];
	char	build_fingerprint[64];
	char	build_hardware[64];
	char	build_radio[64];
	char	build_time[64];
	char	wifi_mac_address[64];
	char	android_id[64];
	char	device_id[64];
	int		width_pixels;
	int		height_pixels;
	int		density_dpi;
	char	register_time[64];
	char	last_use_time[64];
} android;

int order_id = 0;
static db_field android_field[] = {
	{STRUCT_ID, order_id ++, offsetof(android, uuid),				B_STRING,	sizeofof(android, uuid),				"uuid"},
	{STRUCT_ID, order_id ++, offsetof(android, build_brand),		B_STRING,	sizeofof(android, build_brand),			"build_brand"},
	{STRUCT_ID, order_id ++, offsetof(android, build_model),		B_STRING,	sizeofof(android, build_model),			"build_model"},
	{STRUCT_ID, order_id ++, offsetof(android, build_sdk_int),		B_INT,		sizeofof(android, build_sdk_int),		"build_sdk_int"},
	{STRUCT_ID, order_id ++, offsetof(android, build_board),		B_STRING,	sizeofof(android, build_board),			"build_board"},
	{STRUCT_ID, order_id ++, offsetof(android, build_fingerprint),	B_STRING,	sizeofof(android, build_fingerprint),	"build_fingerprint"},
	{STRUCT_ID, order_id ++, offsetof(android, build_hardware),		B_STRING,	sizeofof(android, build_hardware),		"build_hardware"},
	{STRUCT_ID, order_id ++, offsetof(android, build_radio),		B_STRING,	sizeofof(android, build_radio),			"build_radio"},
	{STRUCT_ID, order_id ++, offsetof(android, build_time),			B_STRING,	sizeofof(android, build_time),			"build_time"},
	{STRUCT_ID, order_id ++, offsetof(android, wifi_mac_address),	B_STRING,	sizeofof(android, wifi_mac_address),	"wifi_mac_address"},
	{STRUCT_ID, order_id ++, offsetof(android, android_id),			B_STRING,	sizeofof(android, android_id),			"android_id"},
	{STRUCT_ID, order_id ++, offsetof(android, device_id),			B_STRING,	sizeofof(android, device_id),			"device_id"},
	{STRUCT_ID, order_id ++, offsetof(android, width_pixels),		B_INT,		sizeofof(android, width_pixels),		"width_pixels"},
	{STRUCT_ID, order_id ++, offsetof(android, height_pixels),		B_INT,		sizeofof(android, height_pixels),		"height_pixels"},
	{STRUCT_ID, order_id ++, offsetof(android, density_dpi),		B_INT,		sizeofof(android, density_dpi),			"density_dpi"},
	{STRUCT_ID, order_id ++, offsetof(android, register_time),		B_STRING,	sizeofof(android, register_time),		"register_time"},
	{STRUCT_ID, order_id ++, offsetof(android, last_use_time),		B_STRING,	sizeofof(android, last_use_time),		"last_use_time"},
	{-1,}
};
db_field *_field = android_field;

static db_struct android_struct = {STRUCT_ID, sizeof(android)};
db_struct* _struct = &android_struct;
#endif

#else
db_struct* _struct = NULL;
db_field* _field = NULL;
#endif

bool GenSQLModule::received(Message& msg, int id) {

	if (msg == "engine.start") {
		gensql();
	} else if (msg == "engine.stop") {
	}
	return Module::received(msg, id);
}

INIT_PLUGIN(GenSQLModule);

void GenSQLModule::gensql()
{
	if (_struct == NULL || _field == NULL)
		return;
	sqlite3 *db;
	char buf[32];
	char *errMsg;
	sqlite3_open("sqlite.db", &db);

	{
		string sql = "delete from structure where struct_id=";
		sprintf(buf, "%d", _struct->struct_id);
		sql += buf;

		sqlite3_exec(db, sql.c_str(), NULL, NULL, &errMsg);
	}

	{
		string sql = "delete from field where struct_id=";
		sprintf(buf, "%d", _struct->struct_id);
		sql += buf;

		sqlite3_exec(db, sql.c_str(), NULL, NULL, &errMsg);
	}

	{
		string sql = "insert into structure(struct_id, total_size) values(";

		sprintf(buf, "%d", _struct->struct_id);
		sql += buf;
		sql += ",";

		sprintf(buf, "%d", _struct->total_size);
		sql += buf;
		sql += ")";

		sqlite3_exec(db, sql.c_str(), NULL, NULL, &errMsg);
	}

	{
		string tmp_sql = "insert into field(type, total_size, struct_id, order_index, offset, field_name, description) values(";
		
		db_field *field = _field;
		while (field->struct_id != -1) {
			string sql = tmp_sql;

			sprintf(buf, "%d", field->type);
			sql += buf;
			sql += ",";

			sprintf(buf, "%d", field->size);
			sql += buf;
			sql += ",";

			sprintf(buf, "%d", field->struct_id);
			sql += buf;
			sql += ",";

			sprintf(buf, "%d", field->order_id);
			sql += buf;
			sql += ",";

			sprintf(buf, "%d", field->offset);
			sql += buf;
			sql += ",";

			sprintf(buf, "'%s'", field->name);
			sql += buf;
			sql += ",";

			sprintf(buf, "'%s'", "");
			sql += buf;
			sql += ")";

			field ++;
			sqlite3_exec(db, sql.c_str(), NULL, NULL, &errMsg);
		}
		
		
	}
	sqlite3_close(db);
}